package com.example.projectmanagement.controller;

import com.example.projectmanagement.aop.LogOperation;
import com.example.projectmanagement.dto.UserDto;
import com.example.projectmanagement.dto.UserUpdateDto;
import com.example.projectmanagement.model.User;
import com.example.projectmanagement.model.Role;
import com.example.projectmanagement.model.Permission;
import com.example.projectmanagement.repository.RolePermissionRepository;
import com.example.projectmanagement.service.UserService;
import com.example.projectmanagement.service.FileStorageService;
import com.example.projectmanagement.util.FileSecurityUtil;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/users")
@CrossOrigin
public class UserController {

    @Autowired
    private UserService userService;
    
    @Autowired
    private RolePermissionRepository rolePermissionRepository;
    
    @Autowired
    private FileStorageService fileStorageService;

    /**
     * 获取当前认证用户的ID
     */
    private Long getCurrentUserId() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.getPrincipal() instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            String username = userDetails.getUsername();
            // 根据用户名获取用户ID
            return userService.getUserByUsername(username).map(User::getId).orElse(null);
        }
        return null;
    }

    /**
     * 检查当前用户是否具有指定角色
     */
    private boolean hasRole(String roleName) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            return authentication.getAuthorities().stream()
                    .anyMatch(authority -> authority.getAuthority().equals("ROLE_" + roleName));
        }
        return false;
    }

    /**
     * 获取用户分页列表
     */
    @GetMapping
    @PreAuthorize("hasAnyRole('ADMIN', 'PROJECT_MANAGER')")
    public ResponseEntity<Page<User>> getUsers(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(required = false) String name,
            @RequestParam(required = false) String username,
            @RequestParam(required = false) Integer status) {
        
        Page<User> users = userService.getUsers(page, size, name, username, status);
        return ResponseEntity.ok(users);
    }

    /**
     * 根据ID获取用户
     */
    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        // 获取当前认证用户的ID
        Long currentUserId = getCurrentUserId();
        
        // 验证用户ID一致性（防止水平越权）
        if (!currentUserId.equals(id) && !hasRole("ADMIN")) {
            throw new RuntimeException("无权访问其他用户的数据");
        }
        
        return userService.getUserById(id)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }
    
    /**
     * 获取当前用户信息
     */
    @GetMapping("/current")
    @PreAuthorize("isAuthenticated()")
    public ResponseEntity<User> getCurrentUser() {
        Long currentUserId = getCurrentUserId();
        if (currentUserId == null) {
            return ResponseEntity.status(401).build();
        }
        
        return userService.getUserById(currentUserId)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }

    /**
     * 创建用户
     */
    @PostMapping
    @PreAuthorize("hasRole('ADMIN')")
    @LogOperation(operationType = "CREATE", module = "用户管理", description = "创建新用户")
    public ResponseEntity<User> createUser(@Valid @RequestBody UserDto userDto) {
        // 检查用户名是否已存在
        if (userService.existsByUsername(userDto.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        // 检查是否尝试创建系统管理员用户
        if (userDto.getRole() != null && "ADMIN".equals(userDto.getRole())) {
            throw new RuntimeException("不能创建新的系统管理员用户");
        }
        
        // 如果是PROJECT_MANAGER，改为LECTURER
        if (userDto.getRole() != null && "PROJECT_MANAGER".equals(userDto.getRole())) {
            userDto.setRole("LECTURER");
        }
        
        User user = userService.createUser(userDto);
        return ResponseEntity.ok(user);
    }

    /**
     * 更新用户
     */
    @PutMapping("/{id}")
    @PreAuthorize("isAuthenticated()")
    @LogOperation(operationType = "UPDATE", module = "用户管理", description = "更新用户信息")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody UserUpdateDto userUpdateDto) {
        // 获取当前认证用户的ID
        Long currentUserId = getCurrentUserId();
        
        // 验证用户ID一致性（防止水平越权）
        if (!currentUserId.equals(id) && !hasRole("ADMIN")) {
            throw new RuntimeException("无权访问其他用户的数据");
        }
        
        // 检查是否尝试将用户提升为系统管理员
        if (userUpdateDto.getRole() != null && "ADMIN".equals(userUpdateDto.getRole())) {
            // 获取用户当前角色
            List<Role> currentUserRoles = userService.getUserRoles(id);
            boolean isCurrentlyAdmin = currentUserRoles.stream()
                    .anyMatch(role -> "ADMIN".equals(role.getRoleName()));
            
            if (!isCurrentlyAdmin) {
                throw new RuntimeException("不能将普通用户提升为系统管理员");
            }
        }
        
        // 如果是PROJECT_MANAGER，改为LECTURER
        if (userUpdateDto.getRole() != null && "PROJECT_MANAGER".equals(userUpdateDto.getRole())) {
            userUpdateDto.setRole("LECTURER");
        }
        
        User user = userService.updateUser(id, userUpdateDto);
        return ResponseEntity.ok(user);
    }

    /**
     * 更新用户状态
     */
    @PutMapping("/{id}/status")
    @PreAuthorize("hasRole('ADMIN')")
    @LogOperation(operationType = "UPDATE", module = "用户管理", description = "更新用户状态")
    public ResponseEntity<User> updateUserStatus(@PathVariable Long id, @RequestBody UserDto userDto) {
        User user = userService.updateUserStatus(id, userDto.getStatus());
        return ResponseEntity.ok(user);
    }
    
    /**
     * 更新用户密码（管理员功能）
     */
    @PutMapping("/{id}/password")
    @PreAuthorize("hasRole('ADMIN')")
    @LogOperation(operationType = "UPDATE", module = "用户管理", description = "管理员更新用户密码")
    public ResponseEntity<User> updateUserPassword(@PathVariable Long id, @RequestBody Map<String, String> payload) {
        String newPassword = payload.get("newPassword");
        if (newPassword == null || newPassword.isEmpty()) {
            throw new RuntimeException("新密码不能为空");
        }
        
        // 获取要更新密码的用户
        User userToUpdate = userService.getUserById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        // 检查要更新密码的用户是否拥有ADMIN角色
        List<Role> userRoles = userService.getUserRoles(id);
        boolean isTargetUserAdmin = userRoles.stream()
                .anyMatch(role -> "ADMIN".equals(role.getRoleName()));
        
        // 如果是系统管理员用户，需要额外的安全检查
        if (isTargetUserAdmin) {
            // 获取当前认证用户
            Long currentUserId = getCurrentUserId();
            if (currentUserId == null) {
                throw new RuntimeException("无法获取当前用户信息");
            }
            
            // 检查当前用户是否也是系统管理员
            if (!hasRole("ADMIN")) {
                throw new RuntimeException("只有系统管理员可以修改其他系统管理员的密码");
            }
            
            // 系统管理员不能修改自己的密码（需要通过其他方式）
            if (currentUserId.equals(id)) {
                throw new RuntimeException("系统管理员不能通过此接口修改自己的密码");
            }
        }
        
        User user = userService.updateUserPassword(id, newPassword);
        return ResponseEntity.ok(user);
    }
    
    /**
     * 当前用户修改自己的密码
     */
    @PutMapping("/current/password")
    @PreAuthorize("isAuthenticated()")
    @LogOperation(operationType = "UPDATE", module = "用户管理", description = "用户修改自己的密码")
    public ResponseEntity<User> updateCurrentUserPassword(@RequestBody Map<String, String> payload) {
        String currentPassword = payload.get("currentPassword");
        String newPassword = payload.get("newPassword");
        
        if (currentPassword == null || currentPassword.isEmpty()) {
            throw new RuntimeException("当前密码不能为空");
        }
        
        if (newPassword == null || newPassword.isEmpty()) {
            throw new RuntimeException("新密码不能为空");
        }
        
        if (newPassword.length() < 6) {
            throw new RuntimeException("新密码长度至少6位");
        }
        
        // 获取当前认证用户
        Long currentUserId = getCurrentUserId();
        if (currentUserId == null) {
            throw new RuntimeException("无法获取当前用户信息");
        }
        
        User user = userService.updateCurrentUserPassword(currentUserId, currentPassword, newPassword);
        return ResponseEntity.ok(user);
    }
    
    /**
     * 当前用户更新自己的信息
     */
    @PutMapping("/current")
    @PreAuthorize("isAuthenticated()")
    @LogOperation(operationType = "UPDATE", module = "用户管理", description = "用户更新自己的信息")
    public ResponseEntity<User> updateCurrentUserInfo(@RequestBody UserUpdateDto userUpdateDto) {
        // 获取当前认证用户
        Long currentUserId = getCurrentUserId();
        if (currentUserId == null) {
            throw new RuntimeException("无法获取当前用户信息");
        }
        
        // 使用专门的安全方法更新当前用户信息
        User user = userService.updateCurrentUserInfo(currentUserId, userUpdateDto);
        return ResponseEntity.ok(user);
    }

    /**
     * 删除用户
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    @LogOperation(operationType = "DELETE", module = "用户管理", description = "删除用户")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        // 获取要删除的用户
        User userToDelete = userService.getUserById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        // 检查要删除的用户是否拥有ADMIN角色
        List<Role> userRoles = userService.getUserRoles(id);
        boolean isTargetUserAdmin = userRoles.stream()
                .anyMatch(role -> "ADMIN".equals(role.getRoleName()));
        
        if (isTargetUserAdmin) {
            throw new RuntimeException("不能删除系统管理员用户");
        }
        
        userService.deleteUser(id);
        return ResponseEntity.ok().build();
    }
    
    /**
     * 获取用户的所有权限
     */
    @GetMapping("/{id}/permissions")
    public ResponseEntity<List<Permission>> getUserPermissions(@PathVariable Long id) {
        try {
            // 获取当前认证用户的ID
            Long currentUserId = getCurrentUserId();
            System.out.println("Current authenticated user ID: " + currentUserId);
            
            // 验证用户ID一致性（防止水平越权）
            if (currentUserId == null) {
                System.out.println("Current user ID is null, cannot verify permission");
                throw new RuntimeException("无法获取当前用户信息");
            }
            if (!currentUserId.equals(id) && !hasRole("ADMIN")) {
                System.out.println("Permission denied: currentUserId=" + currentUserId + ", requestedId=" + id);
                throw new RuntimeException("无权访问其他用户的权限信息");
            }
            
            // 获取用户的所有角色
            List<Role> userRoles = userService.getUserRoles(id);
            
            // 获取每个角色的权限并合并
            List<Permission> userPermissions = userRoles.stream()
                    .flatMap(role -> rolePermissionRepository.findPermissionsByRoleId(role.getId()).stream())
                    .distinct()
                    .collect(Collectors.toList());
            
            return ResponseEntity.ok(userPermissions);
        } catch (Exception e) {
            System.out.println("Error in getUserPermissions: " + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }
    
    /**
     * 上传用户头像
     */
    @PostMapping("/current/avatar")
    @PreAuthorize("isAuthenticated()")
    @LogOperation(operationType = "UPDATE", module = "用户管理", description = "用户上传头像")
    public ResponseEntity<Map<String, String>> uploadAvatar(@RequestParam("avatar") MultipartFile file) {
        try {
            // 获取当前认证用户的ID
            Long currentUserId = getCurrentUserId();
            if (currentUserId == null) {
                throw new RuntimeException("无法获取当前用户信息");
            }
            
            // 验证文件类型
            String contentType = file.getContentType();
            if (contentType == null || (!contentType.equals("image/jpeg") && !contentType.equals("image/png"))) {
                throw new RuntimeException("只支持JPG和PNG格式的图片");
            }
            
            // 验证文件大小（限制为6MB）
            long maxSize = 6 * 1024 * 1024; // 6MB
            if (file.getSize() > maxSize) {
                throw new RuntimeException("图片大小不能超过6MB，当前文件大小: " + (file.getSize() / 1024 / 1024) + "MB");
            }
            
            // 保存文件并获取路径
            String filePath = fileStorageService.saveAvatar(file, currentUserId);
            
            // 更新用户头像路径
            userService.updateUserAvatar(currentUserId, filePath);
            
            // 返回成功响应
            Map<String, String> response = new java.util.HashMap<>();
            response.put("avatar", filePath);
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取头像图片
     */
    @GetMapping("/avatar/{userId}")
    @PreAuthorize("permitAll()")
    public ResponseEntity<byte[]> getAvatar(@PathVariable Long userId) {
        try {
            // 验证用户ID
            if (userId == null || userId <= 0) {
                return getDefaultAvatarResponse();
            }
            
            // 获取用户头像路径
            Optional<User> userOpt = userService.getUserById(userId);
            if (userOpt.isPresent() && userOpt.get().getAvatar() != null) {
                String avatarPath = userOpt.get().getAvatar();
                
                // 验证头像路径安全性，防止路径遍历攻击
                if (!isValidAvatarPath(avatarPath)) {
                    return getDefaultAvatarResponse();
                }
                
                Path path = Paths.get(avatarPath);
                if (Files.exists(path) && Files.isRegularFile(path)) {
                    // 验证文件是否在允许的目录内
                    Path uploadDir = Paths.get("uploads/avatars/").toAbsolutePath().normalize();
                    Path filePath = path.toAbsolutePath().normalize();
                    
                    if (!filePath.startsWith(uploadDir)) {
                        return getDefaultAvatarResponse();
                    }
                    
                    byte[] imageBytes = Files.readAllBytes(path);
                    String contentType = "image/jpeg";
                    if (avatarPath.endsWith(".png")) {
                        contentType = "image/png";
                    }
                    return ResponseEntity.ok()
                            .header("Content-Type", contentType)
                            .body(imageBytes);
                }
            }
            // 返回默认头像
            return getDefaultAvatarResponse();
        } catch (Exception e) {
            // 发生异常时返回默认头像
            return getDefaultAvatarResponse();
        }
    }
    
    /**
     * 用户登出
     */
    @PostMapping("/logout")
    @PreAuthorize("isAuthenticated()")
    @LogOperation(operationType = "LOGOUT", module = "认证系统", description = "用户登出")
    public ResponseEntity<Map<String, String>> logout() {
        // 登出操作通常由前端删除JWT token来实现
        // 后端只需要记录日志即可
        Map<String, String> response = new java.util.HashMap<>();
        response.put("message", "登出成功");
        return ResponseEntity.ok(response);
    }
    
    /**
     * 验证头像路径安全性
     * @param avatarPath 头像路径
     * @return 是否安全
     */
    private boolean isValidAvatarPath(String avatarPath) {
        return FileSecurityUtil.isValidAvatarPath(avatarPath);
    }
    
    /**
     * 获取默认头像响应
     */
    private ResponseEntity<byte[]> getDefaultAvatarResponse() {
        try {
            ClassPathResource defaultAvatar = new ClassPathResource("static/images/default-avatar.png");
            if (defaultAvatar.exists()) {
                byte[] imageBytes = Files.readAllBytes(defaultAvatar.getFile().toPath());
                return ResponseEntity.ok()
                        .header("Content-Type", "image/png")
                        .body(imageBytes);
            }
        } catch (IOException e) {
            // 如果默认头像无法读取，返回404
        }
        return ResponseEntity.notFound().build();
    }
}